package com.qingcloud.df.executor.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.qingcloud.base.exception.WamingException;
import com.qingcloud.df.executor.enums.ComponentCommunicationEnum;
import com.qingcloud.df.executor.constant.DateFormatterConstant;
import com.qingcloud.df.executor.queue.publisher.ComponentPublisher;
import com.qingcloud.df.executor.queue.subscriber.ComponentSubscriber;
import com.qingcloud.df.sdk.component.context.CompInstContext;
import com.qingcloud.df.sdk.component.utils.ComponentCommUtils;
import lombok.extern.slf4j.Slf4j;
import oshi.SystemInfo;
import oshi.software.os.OperatingSystem;

import java.io.File;
import java.time.LocalDate;


/**
 * 平台组件相关工具
 *
 * @author wangjinnan
 */
@Slf4j
public class ComponentUtil {


    private ComponentUtil() {
    }

    /**
     * 组件工作目录系统参数KEY
     */
    private static final String COMPONENT_WORK_DIR_KEY = "componentWorkDir";

    /**
     * 复制独立执行的组件到实例工作目录
     *
     * @param componentWorkspace 实例ID
     * @param instWorkspace      组件ID
     */
    public static void copyComponentFile(String componentWorkspace, String instWorkspace) {
        File file = new File(componentWorkspace);
        if (!file.exists()) {
            log.error("component is not exist [{}]", componentWorkspace);
            throw new WamingException("component is not exist [" + componentWorkspace + "]");
        }
        FileUtil.copy(componentWorkspace, instWorkspace, true);
    }

    /**
     * 获取组件当天日志文件
     *
     * @param instanceId 实例ID
     * @return 运行中心的本地绝对路径
     */
    public static String getTodayLogFile(Integer jobId, Integer instanceId, String softwareName, String env) {
        return ComponentCommUtils.getCompInstWorkspace(jobId, instanceId, softwareName, env) + File.separator + "logs"
                + File.separator + LocalDate.now().format(DateFormatterConstant.LOG_DAY_FORMATTER) + ".log";
    }

    /**
     * 获取组件实例指定日期日志文件
     *
     * @param instanceId 实例ID
     * @return 运行中心的本地绝对路径
     */
    public static String getLogFile(Integer jobId, Integer instanceId, String softwareName, String day, String env) {
        return ComponentCommUtils.getCompInstWorkspace(jobId, instanceId, softwareName, env) + File.separator + "logs"
                + File.separator + day + ".log";
    }

    /**
     * 在独立进程的组件启动时，命令行参数增加组件ID标识
     *
     * @param instanceId 组件实例ID
     * @return 实例ID命令行参数内容
     */
    public static String getProcessCommandFlag(Integer jobId, Integer instanceId, String softwareName, String env) {
        return "-D" + COMPONENT_WORK_DIR_KEY + "=" + ComponentCommUtils.getCompInstWorkspace(jobId, instanceId, softwareName, env);
    }

    /**
     * 创建java程序启动命令行
     *
     * @param instance 组件实例信息
     * @return 命令行内容
     */
    public static String[] getProcessCommand(CompInstContext instance) {
        //获取文件绝对路径
        String baseDir = ComponentCommUtils.getCompInstWorkspace(instance.getJobId(), instance.getId(), instance.getSoftwareName(), instance.getEnv());
        String absolutePath = baseDir + File.separator + instance.getSoftwareName() + File.separator + instance.getSoftwareName() + ".jar";

        //获取java虚拟机的绝对路径
        String javaPath = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
        StringBuilder commandBuilder = new StringBuilder();
        commandBuilder.append(javaPath).append(" ");

        //JVM参数
        commandBuilder.append("-Xmx512m -XX:MaxMetaspaceSize=512m ");

        //工作目录参数，放到system property中
        commandBuilder.append(getProcessCommandFlag(instance.getJobId(), instance.getId(), instance.getSoftwareName(), instance.getEnv())).append(" ");

        //jar命令行参数
        commandBuilder.append("-jar ").append(absolutePath);

        String[] commands = new String[3];
        //判断操作系统
        final SystemInfo systemInfo = new SystemInfo();
        final OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
        if ("Windows".equalsIgnoreCase(operatingSystem.getFamily())) {
            //windows操作系统
            commands[0] = "cmd";
            commands[1] = "/c";
        } else {
            commands[0] = "/bin/sh";
            commands[1] = "-c";
        }
        commands[2] = commandBuilder.toString();
        return commands;
    }
    /**
     * 得到组件发布者
     *
     * @param context 实例信息
     * @return 组件发布者
     */
    public static ComponentPublisher getComponentPublisher(CompInstContext context) {
        return SpringUtil.getBean(ComponentCommunicationEnum.AKKA.getPublisher());
    }

    /**
     * 得到组件订阅者
     *
     * @param instance 实例id
     * @return 组件订阅者
     * @throws InstantiationException 实例化异常
     * @throws IllegalAccessException 非法访问异常
     */
    public static ComponentSubscriber getComponentSubscriber(CompInstContext instance) throws Exception {
        Class<? extends ComponentSubscriber> subcriber = ComponentCommunicationEnum.AKKA.getSubcriber();;
        return subcriber.newInstance();
    }

}
